package com.link.base.base.consumer.service;

import com.link.base.base.accnt.model.Account;
import com.link.base.base.consumer.dao.mybatis.mapper.WxConsumerMapper;
import com.link.base.base.consumer.model.QidianAccntWeixin;
import com.link.base.base.enterprise.model.Enterprise;
import com.link.base.base.enterprise.service.EnterpriseService;
import com.link.base.base.user.service.UserService;
import com.link.base.core.basic.interceptors.mybatis.system.KafkaSender;
import com.link.base.wechat.wxlog.model.WxLogModule;
import com.link.base.wechat.wxlog.service.WxLogService;
import com.link.base.wechat.wxplatform.model.WxPlatform;
import com.link.base.wechat.wxplatform.service.WxPlatformService;
import com.link.base.wechat.wxsubscriber.model.Subscriber;
import com.link.base.wechat.wxsubscriber.model.SubscriberList;
import com.link.base.wechat.wxsubscriber.service.WxSubscriberService;
import com.link.core.basic.dao.KeyGenerateDao;
import com.link.core.basic.dao.mapper.BasicMapper;
import com.link.core.basic.service.BasicServiceImpl;
import com.link.core.basic.service.ServiceException;
import com.link.core.util.JsonUtil;
import com.link.core.util.RedisUtil;
import com.link.core.util.StringUtils;
import com.link.core.util.redisclient.LinkRedisClient;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 微信消费者相关服务
 *
 * @author Li Yang
 */
@Service
public class WxConsumerServiceImpl extends BasicServiceImpl<Subscriber> implements WxConsumerService {

    private static final String MALE_STR = "1";
    private static final String FEMALE_STR = "2";
    private static final String Y_STR = "Y";
    private static final String N_STR = "N";

    @Resource
    private EnterpriseService enterpriseService;
    @Resource
    private WxConsumerMapper wxConsumerMapper;
    @Resource
    private WxSubscriberService wxSubscriberService;
    @Resource
    private KeyGenerateDao keyGenerateDao;
    @Resource
    private WxLogService wxLogService;
    @Resource
    private WxPlatformService wxPlatformService;
    @Resource
    private UserService userService;

    private static String formatTime(String createTime) {
        // 将微信传入的CreateTime转换成long类型，再乘以1000
        long msgCreateTime = Long.parseLong(createTime) * 1000L;
        DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return format.format(new Date(msgCreateTime));
    }

    @Override
    public BasicMapper<Subscriber> getBasicMapper() throws Exception {
        if (wxConsumerMapper != null) {
            return wxConsumerMapper;
        }
        throw new ServiceException("PUBLIC-006");
    }

    @Override
    public int insertOrUpdateSub(Subscriber record) throws Exception {
        //时间戳转时间,设置粉丝关注时间
        String res;
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        long lt = new Long(record.getSubscribe_time());
        Date date = new Date(lt * 1000);
        res = simpleDateFormat.format(date);
        record.setSubscribeTimeDate(res);
        int result = wxConsumerMapper.insertOrUpdateSub(record);
        return result;
    }

    @Override
    public Account queryAccountByOpenId(Account account) throws Exception {
        return wxConsumerMapper.queryAccountByOpenId(account);
    }

    @Override
    public void updateWx2code(Account account) {
        wxConsumerMapper.updateWx2code(account);
    }

    @Override
    public WxPlatform queryCorpByWxAppOrOgId(WxPlatform record) throws Exception {
        return wxConsumerMapper.queryCorpByWxAppOrOgId(record);
    }

    /**
     * 将微信粉丝转换为消费者
     * 转换失败的将返回
     */
    @Override
    public List<Account> generateWxSub2Consumer(Subscriber sub, List<Subscriber> subList, Long corpAdminId) throws Exception {
        List<Account> accntList = new ArrayList<Account>();
        if (sub != null) {
            Account account = new Account();
            account.setId(keyGenerateDao.keyGenerate());
            account.setAcctCode(account.getId().toString());
            account.setCreatedBy(sub.getCreatedBy());
            account.setLastUpdatedBy(sub.getLastUpdatedBy());
            account.setCorpid(sub.getCorpid());
            account.setGender(sub.getSex());
            account.setCity(sub.getCity());
            account.setProvince(sub.getProvince());
            account.setCountry(sub.getCountry());
            account.setMainWXOpenid(sub.getOpenid());
            //account.setWxOwnOpenId(sub.getOpenid());
           // account.setWxUnionid(sub.getUnionid());
            account.setAcctChannel(sub.getWxAppId());
           // account.setAppId(sub.getWxAppId());
            account.setAcctType("ChannelConsumer");
           // account.setAcctChannelType("OfficialAccount");
            //account.setFirstEngageTime(DateUtil.dateToStr(new Date(), "yyyy-MM-dd HH:mm:ss"));
            account.setPostnId(sub.getPostnId());
            account.setOrgId(sub.getOrgId());
            // 客户状态默认有效
            account.setAcctStatus("Y");
            Enterprise enterpriseInfo = enterpriseService.getEnterpriseInfo(sub.getCorpid());
            if (enterpriseInfo != null) {
                account.setPriceListId(enterpriseInfo.getDefaultPrice());
            }
            wxConsumerMapper.insertOrUpdateAccount(account);
            accntList.add(account);

            // 同步dmp消费者
            //account.setDataSource2("Link");
            Object object = userService.transformToDmpConsumer(account);
            KafkaSender.sendInfo("CDC_CONSUMER", JsonUtil.toString(object));

        }
        if (subList != null && subList.size() > 0) {
            Account account;
            for (int i = 0; i < subList.size(); i++) {
                account = new Account();
                account.setId(keyGenerateDao.keyGenerate());
                account.setCreatedBy(subList.get(i).getCreatedBy());
                account.setLastUpdatedBy(subList.get(i).getLastUpdatedBy());
                account.setCorpid(subList.get(i).getCorpid());
                account.setGender(subList.get(i).getSex());
                account.setCity(subList.get(i).getCity());
                account.setProvince(subList.get(i).getProvince());
                account.setCountry(subList.get(i).getCountry());
                account.setMainWXOpenid(subList.get(i).getOpenid());
                account.setAcctChannel(subList.get(i).getWxAppId());
                account.setAcctType("ChannelConsumer");
                account.setPostnId(subList.get(i).getPostnId());
                account.setOrgId(subList.get(i).getOrgId());
                account.setAcctName(subList.get(i).getNickname());
                accntList.add(account);

                // 同步dmp消费者
                Object object = userService.transformToDmpConsumer(account);
                KafkaSender.sendInfo("CDC_CONSUMER", JsonUtil.toString(object));
            }
            wxConsumerMapper.batchInsertOrUpdateAccount(accntList);
        }
        return accntList;
    }

    @Override
    public List<Subscriber> queryAllSubByOg(Subscriber record) throws Exception {
        List<Subscriber> result = wxConsumerMapper.queryAllSubByOg(record);
        return result;
    }

    @Override
    public void wxUpdateUnsubscribe(Subscriber record) throws Exception {
        wxConsumerMapper.wxUpdateUnsubscribe(record);
    }

    @Override
    public void unbindWxPlatform(WxPlatform record) throws Exception {
        record.setGrantAuthFlag("N");
        record.setAutoTransConsumer("N");
        wxConsumerMapper.unbindWxPlatform(record);
    }

    @Override
    public Subscriber getSubscriberInfo(String authorizerAppId, String custermname, WxPlatform wxInfo) throws Exception {
        Subscriber sub = wxSubscriberService.getSubscriberInfoByOpenId(authorizerAppId, custermname);
        sub.setWxAppId(authorizerAppId);
        return parseSubscriberInfo(sub, wxInfo);
    }

    @Override
    public Subscriber parseSubscriberInfo(Subscriber subscriber, WxPlatform wxInfo) throws Exception {
        subscriber.setId(keyGenerateService.keyGenerate());
        if (MALE_STR.equals(subscriber.getSex())) {
            subscriber.setSex("MALE");
        } else if (FEMALE_STR.equals(subscriber.getSex())) {
            subscriber.setSex("FEMALE");
        } else {
            subscriber.setSex("UNKNOWN");
        }
        subscriber.setWxAppId(wxInfo.getWx_app_id());
        subscriber.setOgId(wxInfo.getWx_og_id());
        subscriber.setCreatedBy(wxInfo.getCompany_admin_id());
        subscriber.setLastUpdatedBy(wxInfo.getCompany_admin_id());
        subscriber.setCorpid(wxInfo.getCompany_corp());
        subscriber.setPostnId(wxInfo.getPostnId());
        subscriber.setOrgId(wxInfo.getOrgId());
        return subscriber;
    }

    @Override
    public int insertOrUpdateAccountWeixin(QidianAccntWeixin record) throws Exception {
        return wxConsumerMapper.insertOrUpdateAccountWeixin(record);
    }

    @Override
    public void wx2codeUpdate(Account account) throws Exception {
        wxConsumerMapper.wx2codeUpdate(account);
    }

    /**
     * 将微信信息缓存在redis中
     */
    @Override
    public void uploadWxOnRedis(Subscriber sswWs) throws Exception {
        if (sswWs == null || StringUtils.isNull(sswWs.getAccntSeq())) {
            return;
        }
        String redisKey = "WX_SINGLE_MAP_" + sswWs.getAccntSeq();
        //直接塞入redis中
        if (!StringUtils.isNull(sswWs.getAccntSeq()) && !StringUtils.isNull(sswWs.getOpenid())) {
            LinkRedisClient j = null;
            try {
                j = RedisUtil.getJedis();
                j.hset(redisKey, "accntId", StringUtils.null2EmptyString(sswWs.getAccountId().toString()));
                j.hset(redisKey, "accnt_seq", StringUtils.null2EmptyString(sswWs.getAccntSeq()));
                j.hset(redisKey, "openid", StringUtils.null2EmptyString(sswWs.getOpenid()));
                j.hset(redisKey, "nickname", StringUtils.null2EmptyString(sswWs.getNickname()));
                j.hset(redisKey, "sex", StringUtils.null2EmptyString(sswWs.getSex()));
                j.hset(redisKey, "country", StringUtils.null2EmptyString(sswWs.getCountry()));
                j.hset(redisKey, "province", StringUtils.null2EmptyString(sswWs.getProvince()));
                j.hset(redisKey, "city", StringUtils.null2EmptyString(sswWs.getCity()));
                j.hset(redisKey, "headimgurl", StringUtils.null2EmptyString(sswWs.getHeadimgurl()));
                j.hset(redisKey, "subscribe_time_date", StringUtils.null2EmptyString(sswWs.getSubscribe_time()));
                //3分钟有效时间
                j.expire(redisKey, 180);
            } finally {
                RedisUtil.returnResource(j);
            }
        }
    }

    /**
     * 从redis中将微信信息拿到
     */
    @Override
    public Subscriber downloadWxOnRedis(String accntSeq) throws Exception {

        String redisKey = "WX_SINGLE_MAP_" + accntSeq;
        String wxAccntSeq = "";
        //直接从redis中查找
        LinkRedisClient j = null;
        try {
            j = RedisUtil.getJedis();
            wxAccntSeq = j.hget(redisKey, "accnt_seq");
            if (!StringUtils.isNull(wxAccntSeq)) {
                Subscriber ssw = new Subscriber();
                ssw.setAccntSeq(wxAccntSeq);
                ssw.setAccountId(Long.parseLong(j.hget(redisKey, "accntId")));
                ssw.setOpenid(j.hget(redisKey, "openid"));
                ssw.setNickname(j.hget(redisKey, "nickname"));
                ssw.setSex(j.hget(redisKey, "sex"));
                ssw.setCountry(j.hget(redisKey, "country"));
                ssw.setProvince(j.hget(redisKey, "province"));
                ssw.setCity(j.hget(redisKey, "city"));
                ssw.setHeadimgurl(j.hget(redisKey, "headimgurl"));
                ssw.setSubscribeTimeDate(j.hget(redisKey, "subscribe_time_date"));
                return ssw;
            } else {
                return null;
            }
        } finally {
            RedisUtil.returnResource(j);
        }

    }

    @Override
    public void wxAutoTransStatusUpdate(WxPlatform record) throws Exception {
        // 获取微信公众号信息
        WxPlatform wxPlatform = wxPlatformService.queryById(record);
        if (wxPlatform != null) {
            if (N_STR.equals(wxPlatform.getAutoTransConsumer())) {
                // 同步标识为"N"，将标识置为"X"，并触发同步
                wxPlatform.setAutoTransConsumer("X");
                wxConsumerMapper.updateWxAutoTransStatus(wxPlatform);
                // 同步线程
                TransConsumerInfoThread transConsumerInfoThread = new TransConsumerInfoThread(
                        wxPlatform, wxConsumerMapper, this, wxSubscriberService
                );
                Thread thread = new Thread(transConsumerInfoThread);
                thread.start();
            } else if (Y_STR.equals(wxPlatform.getAutoTransConsumer())) {
                // 同步标识为"Y"，将标识置为"N"
                wxPlatform.setAutoTransConsumer("N");
                wxConsumerMapper.updateWxAutoTransStatus(wxPlatform);
            } else {
                throw new ServiceException("CONSUMER-001");
            }
        } else {
            throw new ServiceException("CONSUMER-002", record.getId().toString());
        }
    }

    /**
     * 同步粉丝微信数据，并生成对应的消费者线程
     *
     * @author ouyangzhenqiang
     * @date 2019/03/18 19:01
     */
    class TransConsumerInfoThread implements Runnable {
        private WxPlatform wxPlatform;
        private WxConsumerMapper wxConsumerMapper;
        private WxConsumerService wxConsumerService;
        private WxSubscriberService wxSubscriberService;

        public TransConsumerInfoThread(WxPlatform wxPlatform, WxConsumerMapper wxConsumerMapper,
                                       WxConsumerService wxConsumerService, WxSubscriberService wxSubscriberService) {
            this.wxPlatform = wxPlatform;
            this.wxConsumerMapper = wxConsumerMapper;
            this.wxConsumerService = wxConsumerService;
            this.wxSubscriberService = wxSubscriberService;
        }

        @Override
        public void run() {
            Long batchId = 0L;
            String authorizerAppId = wxPlatform.getWx_app_id();
            Long corpId = wxPlatform.getCorpid();
            try {
                // 拉取微信粉丝数据列表
                SubscriberList subscriberList = wxSubscriberService.getAllSubscriberListNew(authorizerAppId);
                List<Subscriber> list = subscriberList.getList();
                int total = list.size();
                batchId = subscriberList.getBatchId();
                List<Subscriber> parseList = new ArrayList<>();
                if (total > 0) {
                    wxLogService.log(WxLogModule.wxLogUser, "拉取粉丝",
                            "【" + batchId + "】开始批量生成微信粉丝数据...", authorizerAppId, wxPlatform.getCorpid());
                    // 处理粉丝数据，增加组织、帐套等信息
                    for (int i = 0; i < list.size(); i++) {
                        parseList.add(wxConsumerService.parseSubscriberInfo(list.get(i), wxPlatform));
                    }
                    wxConsumerMapper.batchInsertSub(parseList);
                    // 生成消费者数据
                    wxLogService.log(WxLogModule.wxLogUser, "拉取粉丝",
                            "【" + batchId + "】开始批量生成微信消费者数据...", authorizerAppId, wxPlatform.getCorpid());
                    wxConsumerService.generateWxSub2Consumer(null, parseList, wxPlatform.getCompany_admin_id());

                    wxLogService.log(WxLogModule.wxLogUser, "拉取粉丝",
                            "【" + batchId + "】微信粉丝数据及消费者数据同步完毕，合计同步粉丝数据" + total + "条！", authorizerAppId, wxPlatform.getCorpid());
                } else {
                    throw new ServiceException("公众号粉丝数据为0！【" + authorizerAppId + "】");
                }
            } catch (Exception e) {
                wxLogService.error(WxLogModule.wxLogUser, "拉取粉丝",
                        "【" + batchId + "】拉取粉丝数据失败 => " + e.toString(), authorizerAppId, corpId);
            } finally {
                wxPlatform.setAutoTransConsumer("Y");
                wxConsumerMapper.updateWxAutoTransStatus(wxPlatform);
            }

        }
    }

}
